package cn.virens.common.project.generator.database.datasource;

import cn.virens.common.util.exception.APIException;
import cn.virens.common.util.fun.ExFunction;
import com.alibaba.druid.pool.DruidDataSource;
import org.dromara.hutool.setting.Setting;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class DataSourceConfig {
    /**
     * SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COMMENT FROM
     * information_schema.`TABLES` WHERE TABLE_SCHEMA = 'virens_ludeng' AND
     * TABLE_NAME LIKE 'sys_log'
     */

    /***
     * SELECT COLUMN_NAME, COLUMN_DEFAULT, DATA_TYPE, COLUMN_KEY, COLUMN_COMMENT
     * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = 'virens_ludeng' AND
     * TABLE_NAME LIKE 'device'
     */
    private final DruidDataSource dataSource = new DruidDataSource();

    private Connection connection;

    public DataSourceConfig(Setting setting) throws APIException {
        this.setJdbcDriverClass(setting.get("jdbc.driverClass"));
        this.setJdbcPassword(setting.get("jdbc.password"));
        this.setJdbcUsername(setting.get("jdbc.username"));
        this.setJdbcUrl(setting.get("jdbc.url"));
    }

    /**
     * 执行查询语句，并对结果进行循环取值
     *
     * @param sql
     * @param fun
     * @throws Exception
     */
    public <R> List<R> executeQuery(String sql, ExFunction<ResultSet, R> fun) throws Exception {
        try (Statement stm = getConnection().createStatement()) {
            try (ResultSet result = stm.executeQuery(sql)) {
                List<R> answer = new ArrayList<>();

                while (result != null && result.next()) {
                    answer.add(fun.apply(result));
                }

                return answer;
            }
        }
    }

    private synchronized Connection getConnection() throws SQLException {
        if (this.connection == null || this.connection.isClosed()) {
            this.connection = dataSource.getConnection();
        }

        return connection;
    }

    public void setJdbcDriverClass(String jdbcDriverClass) {
        this.dataSource.setDriverClassName(jdbcDriverClass);
    }

    public void setJdbcPassword(String jdbcPassword) {
        this.dataSource.setPassword(jdbcPassword);
    }

    public void setJdbcUsername(String jdbcUsername) {
        this.dataSource.setUsername(jdbcUsername);
    }

    public void setJdbcUrl(String jdbcUrl) {
        this.dataSource.setUrl(jdbcUrl);
    }

}
